#ifndef PADDLE_TTS_SERVING_FRONT_TEXT_NORMALIZE_H
#define PADDLE_TTS_SERVING_FRONT_TEXT_NORMALIZE_H

#include <codecvt>
#include <map>
#include <regex>
#include <string>
#include <iostream>
#include "absl2/strings/str_split.h"
#include "absl2/strings/strip.h"
#include "front/type_conv.h"

using namespace std;

namespace ppspeech {

class TextNormalizer {
public:
	TextNormalizer();
	~TextNormalizer();

	vector<wstring> WstrSplitByPunctuation(const wstring& fcpInSentence);
	void SentenceNormalize(wstring* fpInWsentence);
	void SetUseLanguage(wstring* fpInWsentence, string fcpInLanguageName);

//----------------------------------------------------
private:
	//------------------------   中文数字   ----------------------------
	const vector<string> mcVecNumberYi1  = {"零", "壹", "二", "三", "四", "五", "六", "七", "八", "九"};
	const vector<string> mcVecNumberYao1 = {"零", "幺", "二", "三", "四", "五", "六", "七", "八", "九"};

	string TnZh_EachDigit2Str(const string& fcInputNumStr, const bool fcInUseAllYao1);

	string TnZh_NumNegDec2Int(const string& fcInputNumStr,
							const bool fcInUseAll1Yi1, const bool fcInUseAll1Yao1,
							const bool fcInUseOnly2Liang3, const bool fcInUseAll2Liang3);

	string TnZh_Digit2Int(const string& fcInputNumStr, const bool fcInUseZero,
						const bool fcInUseAll1Yi1, const bool fcInUseAll1Yao1,
						const bool fcInUseOnly2Liang3, const bool fcInUseAll2Liang3);

	string TnZh_Num2Chinese(const string& fcInputNumStr, const bool fcInUseZero);

	string TnZh_Section2Chinese(const unsigned int fcInSection, const bool zero_of_time);

	//------------------------   英文数字   ----------------------------

	string TnEn_Num2English(const long number);
	string TnEn_OrdinalNum2English(const long ordinal_number);
	string TnEn_EachDigit2Str(const string& fcInputNumStr);
	string TnEn_NumNegDec2Int(const string& fcInputNumStr);

	//------------------------   语言类型   ----------------------------

	LanguageEnum GetAutoLanguageEnum(wstring fInWsentence);
	LanguageEnum mUseLanguage;

	//------------------------   正则化   ----------------------------
	void TnReWebsite(wstring* fpInWsentence);

	void TnReInitialSymbol(wstring* fpInWsentence, const LanguageEnum fcInLanguage);
	void TnReFinallySymbol(wstring* fpInWsentence, const LanguageEnum fcInLanguage);

	void TnReLetterAa(wstring* fpInWsentence);

	void TnReCurrency(wstring* fpInWsentence, const LanguageEnum fcInLanguage);

	void TnReEnAmPm(wstring* fpInWsentence, const LanguageEnum fcInLanguage);

	void TnReLetterNumber(wstring* fpInWsentence, const LanguageEnum fcInLanguage);
	void TnReNumberLetter(wstring* fpInWsentence, const bool fcInAppendFlag, const LanguageEnum fcInLanguage);

	void TnReDecimalLetter(wstring* fpInWsentence, const LanguageEnum fcInLanguage);
	void TnReLetterDecimal(wstring* fpInWsentence, const LanguageEnum fcInLanguage);

	void TnReLetterSplit(wstring* fpInWsentence);

	void TnReChineseDate(wstring* fInWsentence, const LanguageEnum fcInLanguage);
	void TnReChineseCentury(wstring* fInWsentence, const LanguageEnum fcInLanguage);

	void TnReColon(wstring* fpInWsentence, const LanguageEnum fcInLanguage);

	void TnReComma(wstring* fpInWsentence, const LanguageEnum fcInLanguage);

	void TnReDashLetter(wstring* fpInWsentence, const LanguageEnum fcInLanguage);
	void TnReDashDecimal(wstring* fpInWsentence, const LanguageEnum fcInLanguage);
	void TnReDashColon(wstring* fpInWsentence, const LanguageEnum fcInLanguage);
	void TnReDash(wstring* fpInWsentence, const LanguageEnum fcInLanguage);

	void TnReDotLetter(wstring* fpInWsentence, const LanguageEnum fcInLanguage);
	void TnReDotNumber(wstring* fpInWsentence, const LanguageEnum fcInLanguage);

	void TnReSlash(wstring* fpInWsentence, const LanguageEnum fcInLanguage);
	void TnReSlashUnit(wstring* fpInWsentence, const LanguageEnum fcInLanguage);
	void TnReZhSlashUnit(wstring* fpInWsentence, const LanguageEnum fcInLanguage);

	void TnRePercentage(wstring* fpInWsentence, const LanguageEnum fcInLanguage);

	void TnReWavyline(wstring* fpInWsentence, const LanguageEnum fcInLanguage);

	void TnReNo2Number(wstring* fpInWsentence, const LanguageEnum fcInLanguage);

	void TnReNegDecNum(wstring* fpInWsentence, const bool fcInWithInteger, const LanguageEnum fcInLanguage);

	void TnReZhQuantifiers(wstring* fpInWsentence, const LanguageEnum fcInLanguage);

	void TnReScientificNotation(wstring* fpInWsentence, const LanguageEnum fcInLanguage);
	void TnReTrigonometric(wstring* fpInWsentence, const LanguageEnum fcInLanguage);
	void TnReLatitudeLongitude(wstring* fpInWsentence, const LanguageEnum fcInLanguage);

	void TnReMobilePhone(wstring* fpInWsentence, const LanguageEnum fcInLanguage);
	void TnReLandlinePhone(wstring* fpInWsentence, const LanguageEnum fcInLanguage);
	void TnReOtherPhone(wstring* fpInWsentence, const LanguageEnum fcInLanguage);

	void TnReChinesePost(wstring* fpInWsentence, const LanguageEnum fcInLanguage);
	void TnReEnglishPost(wstring* fpInWsentence);
	void TnReEnNumAndNum(wstring* fpInWsentence);

	void TnReEnAtNumber(wstring* fpInWsentence, const LanguageEnum fcInLanguage);
	void TnReEnDate(wstring* fpInWsentence, const LanguageEnum fcInLanguage);


	bool IsCharNumber(const char& fpInChar);
	bool IsStrAllNumber(const string& fpInSentence);
	bool IsWstrAllNumber(const wstring& fpInWsentence);

	bool IsWcharZhLetter(const wchar_t& fpInWchar);
	bool IsWcharEnLetter(const wchar_t& fpInWchar);
	bool IsCharEnLetter(const char& fpInChar);
	bool IsWcharNumber(const wchar_t& fpInWchar);

	void TnReGreekAlphabet(wstring* fpInWsentence);


	int GetWstrFirstNumberPosition(const wstring& fpInWsentence);
	bool CheckIsDateNianyueri(const vector<string>& fpInVecDate);


	vector<wstring> GetWstrPositionNextWords(const wstring& fpInWsentence, const size_t fcInPosition, const size_t fcInWordsNumber, const enum LanguageEnum fcInLanguage);
	string NextWordsConnectAfterString(const vector<wstring> fcpInVecNextWords, const size_t fcInWordsNumber, const enum LanguageEnum fcInLanguage);
	vector<wstring> GetWstrPositionLastWords(const wstring& fpInWsentence, const size_t fcInPosition, const size_t fcInWordsNumber, const enum LanguageEnum fcInLanguage);
	string LastWordsConnectBeforeString(const vector<wstring> fcpInVecLastWords, const size_t fcInWordsNumber, const enum LanguageEnum fcInLanguage);

	//----------------------------------
	enum RepleceMethodEnum {
		RME_none,

		RME_zh_colon_ratio,			RME_en_colon_ratio,

		RME_zh_colon_dianfenmiao,	RME_en_colon_dianfenmiao,
		RME_zh_colon_dianfen,		RME_en_colon_dianfen,

		RME_zh_chinesedate,			RME_en_chinesedate,		RME_en_year,

		RME_zh_subtraction,			RME_en_subtraction,

		RME_zh_telephone,			RME_en_telephone,

		RME_zh_range,				RME_en_range,

		RME_zh_letter_number,		RME_en_letter_number,

		RME_zh_fraction,			RME_en_fraction,

		RME_zh_negative_decimal,	RME_en_negative_decimal,	RME_en_ordinal_number,

		RME_zh_percent,				RME_en_percent,

		RME_zh_integer_1yix_2liang3_yi1,	RME_zh_integer_yi1_liang3,
		RME_zh_digit_yi1,
		RME_digit_yao,

		RME_en_website,
	};

	string ReplaceMethod(const vector<string>& fpInVecItems, RepleceMethodEnum fcInRepleceMethod);
	int FindPatternCount(const string& fpInSentence, const string& fpInPattern);
	size_t FindVectorPatternCount(const vector<wstring>& fpInVecWords, const vector<string>& fpInVecPatterns, const enum LanguageEnum fcInLanguage);
	void WstrReplacePosition(wstring* fpInSentence, const int fcInPosition, const int fcInLength, const wstring& fcpInWstrReplace);	//替换

	//----------------------------------
	const vector<string> VecStr_NotSplitUpperWord = {
		"TFBOYS", "TFBOY", "BLACKPINK", "UNNO", "TOP", "INNOCOCO", "BOSS", "HI", "HELLO", "INTO", "CCTV", "WIN", "AUTO",
		"PUBLISHED", "AUGUST", "MIN", "READ", "SARS", "YO", "OR", "VIP", "WHO", "MAX", "ACCA", "YES", "STEM", "BLOOD", "WOW", "BGM",
		"AI", "UBTECH", "ROBOTICS", "CORP", "LTD", "NORTH", "AMERICA", "RESEARCH", "AND", "DEVELOPMENT", "CENTER", "LIMITED", "WRC", "GITEX",
		"MIUI", "SDK",
	};


	const map<string, string> mcAbbr = {
		{"jan", "january"},
		{"feb", "february"},
		{"mar", "march"},
		{"apr", "april"},
		//{"may", "may"},
		{"jun", "june"},
		{"jul", "july"},
		{"aug", "august"},
		{"sept", "september"},
		{"sep", "september"},
		{"oct", "october"},
		{"nov", "november"},
		{"dec", "december"},

		{"mrs", "misses"},
		{"mr", "mister"},
		{"dr", "doctor"},
		{"st", "saint"},
		{"co", "company"},
		{"jr", "junior"},
		{"maj", "major"},
		{"gen", "general"},
		{"drs", "doctors"},
		{"rev", "reverend"},
		{"lt", "lieutenant"},
		{"hon", "honorable"},
		{"sgt", "sergeant"},
		{"capt", "captain"},
		{"esq", "esquire"},
		{"ltd", "limited"},
		{"col", "colonel"},
		{"ft", "fort"},
		{"mt", "mount"}
	};
};
}  // namespace ppspeech

#endif